package com.newy.service.sys;

import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import javax.annotation.Resource;

import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;

import com.newy.core.AppException;
import com.newy.core.BaseService;
import com.newy.dao.sys.DictDao;
import com.newy.domain.sys.Dict;

/**
 * 
 * @author linzongxue 2012-2-18
 *
 */
@Service
@Transactional
public class DictService extends BaseService{
	@Resource private DictDao dictDao;
	
	/**
	 * 字典缓存，用于字典的显示。
	 * 结构为：{字典类型名称: 字典项列表}
	 */
	private static final Map<String, List<Dict>> dictCache = new ConcurrentHashMap<String, List<Dict>>();
	
	@Transactional(readOnly = true)
	public List<Dict> getAllDictTypes(){
		return dictDao.getAllDictTypes();
	}

	/**
	 * 根据字典类型名称获取所有字典项，找不到字典类型返回null
	 * @param typeName 字典类型名称
	 */
	@Transactional(readOnly = true)
	public List<Dict> getDictItems(String typeName){
		//先从缓存中读取，缓存中不存在才读取数据库
		List<Dict> items = dictCache.get(typeName);
		if (items == null){
			Dict type = dictDao.findTypeByName(typeName);
			if (type == null) return null;
			items = dictDao.getDictItems(type.getId());
			dictCache.put(typeName, items);
		}
		return items;
	}
	
	/**
	 * 根据字典类型ID获取所有字典项
	 * @param typeName 字典类型名称
	 */
	@Transactional(readOnly = true)
	public List<Dict> getDictItems(Long id){
		return dictDao.getDictItems(id);
	}

	@Transactional(readOnly = true)
	public Dict getDict(Long id){
		return dictDao.get(id);
	}
	
	public void saveDictType(Dict dict){
		//检查重名
		if (!dictDao.isPropsUnique(dict, "name"))
			throw new AppException("保存失败：字典类型(%s)已存在", dict.getName());
		//插入或修改
		dictDao.save(dict);
	}
	
	/**
	 * 删除字典类型，同时所属字典项
	 * @param id 字典类型Id
	 */
	public void deleteDictType(Long id){
		Dict type = dictDao.get(id);
		if (type == null) return;
		//删除字典项
		for (Dict item : dictDao.getDictItems(id)){
			dictDao.delete(item.getId());
		}
		//删除字典类型
		dictDao.delete(id);
		//删除缓存
		dictCache.remove(type.getName());
	}
	
	/**
	 * 保存指定类型的字典项，属于全集保存
	 * @param typeId 字典类型ID
	 * @param items 所有字典项
	 */
	public synchronized void saveDictItems(Long typeId, List<Dict> items){
		Assert.notNull(typeId);
		this.checkDictItems(items);
		List<Dict> oldItems = dictDao.getDictItems(typeId);
		//添加和修改新字典项
		for (Dict newItem : items){
			newItem.setParentId(typeId);
			//在旧字典项中查找，找到就是修改，找不到就是添加（不要用判断id是否要null的方法，那样多人修改时不准确）
			int i = oldItems.indexOf(newItem);
			if (i > -1){
				dictDao.evict(oldItems.get(i));
				oldItems.remove(i); //从旧字典项移除，表示不删除
			}
			else{
				newItem.setId(null);
			}
			dictDao.save(newItem);
		}
		//删除旧字典项
		for (Dict d : oldItems){
			dictDao.delete(d.getId());
		}
		//从缓存中删除
		Dict type = dictDao.get(typeId);
		dictCache.remove(type.getName());
	}
	
	/**
	 * 检查字典项的值是否有重复，有则抛出异常
	 * @param items
	 */
	private void checkDictItems(List<Dict> items){
		if (items == null) return;
		for (int i = 0; i < items.size(); i ++){
			for (int j = i + 1; j < items.size(); j ++){
				if (items.get(i).getValue() == items.get(j).getValue()){
					throw new AppException("字典值重复：%s", items.get(i).getValue());
				}
			}
		}
	}
}
